package com.zwy.lock;

import com.zwy.util.RedisCommonUtil;
import com.zwy.util.RedisStringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;

@Component
public class RedisLock {
	private final int dbIndex = 15;

	@Autowired
	private RedisStringUtil redisStringUtil;
	@Autowired
	private RedisCommonUtil redisCommonUtil;


	/**
	 * 加锁
	 * 使用方式为：
	 * lock();
	 * try{
	 * 	  executeMethod();
	 * }finally{
	 * 	 unlock();
	 * }
	 * @param timeout timeout的时间范围内轮询锁
	 * @param expire 设置锁超时时间
	 * @return 成功 or 失败
	 */
	public boolean lock(String key, long timeout, long expire){
		long nanoTime = System.nanoTime();
		try {
			//在timeout的时间范围内不断轮询锁
			while (System.nanoTime() - nanoTime < timeout * 1_000_000_000) {
				//锁不存在的话，设置锁并设置锁过期时间，即加锁
				if (this.redisStringUtil.setnx(dbIndex, key, "true")) {
					this.redisCommonUtil.expire(dbIndex, key, expire);//设置锁过期时间是为了在没有释放
					return true;
				}
				TimeUnit.MILLISECONDS.sleep(100);
			}
		} catch (Exception e) {
			throw new CacheLockException("locking error",e);
		}
		return false;
	}

	public  void unlock(String key) {
		redisCommonUtil.del(dbIndex, key);//直接删除
	}
}
